package ar.edu.sovietrussia.customcomponents.loanhandling;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;

import services.user.LoanService;
import users.Person;
import ar.edu.sovietrussia.customcomponents.util.BookAndStatusWrapper;
import ar.edu.sovietrussia.customcomponents.util.InwardReplaceablePanel;
import books.Loan;

/**
 * Component for loans creation and renewal
 */

@AuthorizeInstantiation({ "USER", "ADMIN" })
public class SearchCurrentLoansByUserComponent extends InwardReplaceablePanel {

    private static final long serialVersionUID = -3393709759554957388L;

    @SpringBean(name = "service.loan")
    private LoanService loanService;

    private List<BookAndStatusWrapper> tableData;

    private Form<String> form = new Form<String>("loansByUserForm");

    public Form<String> getForm() {
        return form;
    }

    public void setForm(final Form<String> form) {
        this.form = form;
    }

    public LoanService getLoanService() {
        return loanService;
    }

    public SearchCurrentLoansByUserComponent(final String id, final Class<?> clazz) {
        super(id);
        setOutputMarkupId(true);

        final Person aModel = (Person) getSession().getAttribute("model");

        // First, initialize table data

        form.add(new Label("introLabel", "Prestamos vigentes de: "));

        form.add(new Label("userLabel", aModel.getSurname() + "," + aModel.getName()));

        // The table with checkboxes
        ListView listView = initializeLoans(aModel);

        // Button to Gestionar Devolucion
        form.add(new AjaxButton("gestionarDevolucion_button") {
            private static final long serialVersionUID = 511988479544143879L;

            @Override
            protected void onSubmit(final AjaxRequestTarget target, final Form<?> aForm) {
                SearchCurrentLoansByUserComponent.this.finishSelectedLoans(aModel);

                SearchCurrentLoansByUserComponent.this.initializeLoans(aModel);
                target.add(SearchCurrentLoansByUserComponent.this);
            }

            @Override
            protected void onError(final AjaxRequestTarget target, final Form<?> aForm) {
                throw new UnsupportedOperationException();
            }
        });

        // Button to Renovar
        AjaxButton button = new AjaxButton("renovar_button") {
            private static final long serialVersionUID = 5119888790644143879L;

            @Override
            protected void onSubmit(final AjaxRequestTarget target, final Form<?> aForm) {
                SearchCurrentLoansByUserComponent.this.renewSelectedLoans(aModel);

                SearchCurrentLoansByUserComponent.this.initializeLoans(aModel);
                target.add(SearchCurrentLoansByUserComponent.this);
            }

            @Override
            protected void onError(final AjaxRequestTarget target, final Form<?> aForm) {
                throw new UnsupportedOperationException();
            }
        };

        form.add(button);

        form.add(new Button("goBackButton") {
            private static final long serialVersionUID = 4814093770496218067L;

            @Override
            public void onSubmit() {
                SearchCurrentLoansByUserComponent.this.goBack(clazz);
            }
        });
        this.add(form);

    }

    private ListView initializeLoans(final Person aModel) {

        tableData = new ArrayList<BookAndStatusWrapper>();
        tableData.addAll(wrapLoansForView(aModel));

        String selectionTableName = "selectionTable";

        @SuppressWarnings("unchecked")
        ListView listView = new ListView(selectionTableName, tableData) {

            private static final long serialVersionUID = 1L;

            @Override
            protected void populateItem(final ListItem item) {
                BookAndStatusWrapper wrapper = (BookAndStatusWrapper) item.getModelObject();
                item.add(new Label("bookName", wrapper.getBookName()));
                item.add(new Label("expiringDate", wrapper.getExpiringDate()));
                item.add(new CheckBox("check", new PropertyModel(wrapper, "selected")));
            }
        };
        listView.setReuseItems(false);

        replaceIfExists(listView, selectionTableName);

        return listView;
    }

    private void replaceIfExists(final ListView listView, final String componentID) {

        if (form.get(componentID) == null) {
            form.add(listView);
        } else {
            form.replace(listView);
        }
    }

    public List<BookAndStatusWrapper> getTableData() {
        return tableData;
    }

    public void setTableData(final List<BookAndStatusWrapper> tableData) {
        this.tableData = tableData;
    }

    public void setLoanService(final LoanService loanService) {
        this.loanService = loanService;
    }

    // ---------------------------------------------------------------//
    // ---------------CONTROLLER LOGIC AND OTHER ---------------------//
    // ---------------------------------------------------------------//

    private List<BookAndStatusWrapper> wrapLoansForView(final Person aModel) {
        List<Loan> iterable = loanService.getCurrentLoansOf(aModel);
        List<BookAndStatusWrapper> ret = new ArrayList<BookAndStatusWrapper>();

        for (Loan it : iterable) {
            BookAndStatusWrapper newEntry = new BookAndStatusWrapper(it.getBookInfo().getTitle(), it.getEnd()
                    .toString(), it.getId());
            ret.add(newEntry);
        }

        return ret;
    }

    private List<Loan> getSelectedLoansFromView(final Person aModel) {
        Iterator<BookAndStatusWrapper> it = tableData.iterator();
        List<Loan> ret = new ArrayList<Loan>();

        while (it.hasNext()) {
            BookAndStatusWrapper next = it.next();

            if (next.getSelected()) {
                ret.add(loanService.getSpecificLoanOf(aModel, next.getBookName()));
            }
        }

        return ret;
    }

    private void renewSelectedLoans(final Person aModel) {
        List<Loan> selected = getSelectedLoansFromView(aModel);

        for (Loan it : selected) {
            loanService.renewLoan(it);
        }
    }

    private void finishSelectedLoans(final Person aModel) {
        List<Loan> selected = getSelectedLoansFromView(aModel);

        for (Loan it : selected) {
            loanService.returnLoan(it);
        }

    }

}
